﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace UI
{
    using static UI.Utilitys;
    /// <summary>
    /// UIElement 对象处理过程
    /// UI的显示逻辑在这个对象中实现，同时提供了多个接口对不同的处理过程插入执行代码
    /// </summary>
    internal static class UIElementHandlers
    {
        private static List<IUIElementHandler> _showHandlers = new List<IUIElementHandler>();

        private static List<IUIElementHandler> _freezHandlers = new List<IUIElementHandler>();

        private static List<IUIElementHandler> _closeHandlers = new List<IUIElementHandler>();

        internal static void AddHandler(IUIElementOpenHandler handler)
        {
            _showHandlers.Add(handler);
        }

        internal static void AddHandler(IUIElementFreezHandler handler)
        {
            _freezHandlers.Add(handler);
        }

        internal static void AddHandler(IUIElementCloseHandler handler)
        {
            _closeHandlers.Add(handler);
        }

        private struct HandlerData 
        {
            public UIElement UI;
            public IList<IUIElementHandler> Handlers;
            public Action BeforeAction;
            public Func<UIElement, IEnumerator> PlayAnimationAction;
            public Action AfterAction;
            public IEnumerator Before()
            {
                if (UI == null || Handlers == null) yield break;
                List<Coroutine> coroutines = new List<Coroutine>();
                var self = this;
                if (BeforeAction != null)
                {
                    BeforeAction();
                }
                ForAction(Handlers, (handler) =>
                {
                    var routine = handler.BeforeHandler(self.UI);
                    var coroutine = StartCoroutine(routine);
                    coroutines.Add(coroutine);
                });
                yield return ForWaitCoroutines(coroutines);
                if (PlayAnimationAction != null)
                    yield return PlayAnimationAction(UI);
            }
            public IEnumerator After()
            {
                if (UI == null || Handlers == null) yield break;
                List<Coroutine> coroutines = new List<Coroutine>();
                var self = this;
                ForAction(Handlers, (handler) =>
                {
                    var routine = handler.AfterHandler(self.UI);
                    var coroutine = StartCoroutine(routine);
                    coroutines.Add(coroutine);
                });
                yield return ForWaitCoroutines(coroutines);
                if (AfterAction != null)
                {
                    AfterAction();
                }
            }
        }

        private static IEnumerator DoHandler(HandlerData data)
        {
            yield return data.Before();
            yield return data.After();
        }

        private static IEnumerator DoOpen(UIElement ui)
        {
            if (ui.State == UIState.Showed) yield break;
            yield return DoHandler(new HandlerData()
            {
                UI = ui,
                Handlers = _showHandlers,
                BeforeAction = () =>
                {
                    Debug.Log(ui.name + " 开始显示");
                },
                PlayAnimationAction = UIAnimationHandlers.PlayOpenAnimation,
                AfterAction = () =>
                {
                    ui.State = UIState.Showed;
                    Debug.Log(ui.name + " 显示完成");
                },
            });
        }

        private static IEnumerator DoClose(UIElement ui)
        {
            if (ui.State == UIState.Hided) yield break;
            yield return DoHandler(new HandlerData()
            {
                UI = ui,
                Handlers = _closeHandlers,
                BeforeAction = () => Debug.Log(ui.name + " 开始关闭"),
                PlayAnimationAction = UIAnimationHandlers.PlayCloseAnimation,
                AfterAction = () =>
                {
                    ui.State = UIState.Hided;
                    Debug.Log(ui.name + " 完成关闭");
                },
            });
        }

        private static IEnumerator DoFreez(UIElement ui)
        {
            if (ui.State == UIState.Freezed) yield break;
            yield return DoHandler(new HandlerData()
            {
                UI = ui,
                BeforeAction = null,
                Handlers = _freezHandlers,
                PlayAnimationAction = null,
                AfterAction = () =>
                {
                    ui.State = UIState.Freezed;
                },
            });
        }

        internal static void Open(UIElement ui)
        {
            if (ui == null) return;
            StartCoroutine(DoOpen(ui));
        }

        internal static void Close(UIElement ui)
        {
            if (ui == null) return;
            StartCoroutine(DoClose(ui));
        }

        internal static void Freez(UIElement ui)
        {
            if (ui == null) return;
            StartCoroutine(DoFreez(ui));
        }
    }


}
